#include "vd_mouse.h"

/*
* module para
*/
static vd_ssocket vd_mouse_ssock;

static int server_port = 19800;
module_param(server_port, int, S_IRUGO);

static int server_buff_size = 32;
module_param(server_buff_size, int, S_IRUGO);

struct input_dev *vd_mouse_input_dev;
static struct platform_device *vd_mouse_dev;

/* Proc remote mouse event data from net */
static void vd_mouse_net_data_proc(char *buff, int size)
{
    int i = 0;
    struct input_event *event_key;

    printk("vd mouse recv %d\n", size);

    if (size < sizeof(struct input_event))
    {
        printk("recv remote input_event error\n");
        return;
    }

    event_key = (struct input_event*)buff;

    for (i=0; i < size / sizeof(struct input_event); ++i)
    {
        /* Report relative coordinates via the event interface */
        input_event(vd_mouse_input_dev, event_key[i].type, event_key[i].code, event_key[i].value);
        input_sync(vd_mouse_input_dev);
    }
}

static int vd_reg_mouse_dev(void)
{
    int err = 0;

    vd_mouse_dev = platform_device_register_simple("vd_vms", -1, NULL, 0);

    if (IS_ERR(vd_mouse_dev)) {
        printk("vd_vms_init: error\n");
        return PTR_ERR(vd_mouse_dev);
    }

    /* Allocate an input device data structure */
    vd_mouse_input_dev = input_allocate_device();

    if (!vd_mouse_input_dev) {
        printk("input_allocate_device() failed\n");
        return -ENOMEM;
    }

    vd_mouse_input_dev->name = DEVICE_NAME;

    /* Announce that the virtual mouse will generate what */
    vd_mouse_input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) | BIT(EV_REP);
	vd_mouse_input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
	vd_mouse_input_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);

	//vd_mouse_input_dev->id.bustype = VD_BUSTYPE;
	//vd_mouse_input_dev->id.vendor = VD_VENDOR;
	//vd_mouse_input_dev->id.version = VD_VER;

    /* Register with the input subsystem */
    err = input_register_device(vd_mouse_input_dev);
	if (err) {
		input_free_device(vd_mouse_input_dev);
		return err;
	}

    printk("Virtual Mouse Driver Initialized.\n");

    return 0;
}

static int vd_unreg_mouse_dev(void)
{
    /* Unregister from the input subsystem */
    input_unregister_device(vd_mouse_input_dev);

    /* Unregister driver */
    platform_device_unregister(vd_mouse_dev);

    return 0;
}

static int __init vd_mouse_init(void)
{
    int err = 0;

	vd_reg_mouse_dev();

	vd_mouse_ssock.proc_func = vd_mouse_net_data_proc;
	vd_mouse_ssock.buff_size = server_buff_size;
	vd_mouse_ssock.buff = kmalloc(vd_mouse_ssock.buff_size, GFP_KERNEL);

    if (vd_mouse_ssock.buff == NULL)
        return err;

	err = vd_start_server_udp_socket(&vd_mouse_ssock, server_port);

	if (err != 0)
    {
        printk("creating mouse socket fails\n");
    }

	return err;
}

static void __exit vd_mouse_exit(void)
{
	vd_close_server_udp_socket(&vd_mouse_ssock);

	printk("vd close mouse server_socket\n");

	kfree(vd_mouse_ssock.buff);

	vd_unreg_mouse_dev();

	printk("Virtual Mouse Driver unloaded.\n");
}

module_init(vd_mouse_init);
module_exit(vd_mouse_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR( "lzhang" );
